/**
 * Created by MaoLin on 2020/11/18.
 */
import Vue from 'vue';
import { Message,Notification} from 'element-ui';
export function toast (options) {

  if (options.showClose === undefined) {
    options.showClose = true;
  }
  if (options.type === undefined) {
    options.type = 'success';
  }
  if (options.duration === undefined) {
    options.duration = 2000;
  }
  return Message(options);
}

/**
 * Parse the time to string
 * @param {(Object|string|number)} time
 * @param {string} cFormat
 * @returns {string | null}
 */
export function parseTime (time, cFormat) {
  if (arguments.length === 0 || !time) {
    return null;
  }
  const format = cFormat || '{y}-{m}-{d} {h}:{i}:{s}';
  let date;
  if (typeof time === 'object') {
    date = time;
  } else {
    if ((typeof time === 'string')) {
      if ((/^[0-9]+$/.test(time))) {
        // support "1548221490638"
        time = parseInt(time);
      } else {
        // support safari
        // https://stackoverflow.com/questions/4310953/invalid-date-in-safari
        time = time.replace(new RegExp(/-/gm), '/');
      }
    }

    if ((typeof time === 'number') && (time.toString().length === 10)) {
      time = time * 1000;
    }
    date = new Date(time);
  }
  const formatObj = {
    y: date.getFullYear(),
    m: date.getMonth() + 1,
    d: date.getDate(),
    h: date.getHours(),
    i: date.getMinutes(),
    s: date.getSeconds(),
    a: date.getDay()
  };
  return format.replace(/{([ymdhisa])+}/g, (result, key) => {
    const value = formatObj[key];
    // Note: getDay() returns 0 on Sunday
    if (key === 'a') {
      return ['日', '一', '二', '三', '四', '五', '六'][value];
    }
    return value.toString().padStart(2, '0');
  });
}

/**
 * @param {number} time
 * @param {string} option
 * @returns {string}
 */
export function formatTime (time, option) {
  if (('' + time).length === 10) {
    time = parseInt(time) * 1000;
  } else {
    time = +time;
  }
  const d = new Date(time);
  const now = Date.now();

  const diff = (now - d) / 1000;

  if (diff < 30) {
    return '刚刚';
  } else if (diff < 3600) {
    // less 1 hour
    return Math.ceil(diff / 60) + '分钟前';
  } else if (diff < 3600 * 24) {
    return Math.ceil(diff / 3600) + '小时前';
  } else if (diff < 3600 * 24 * 2) {
    return '1天前';
  }
  if (option) {
    return parseTime(time, option);
  } else {
    return (
      d.getMonth() +
      1 +
      '月' +
      d.getDate() +
      '日' +
      d.getHours() +
      '时' +
      d.getMinutes() +
      '分'
    );
  }
}

/**
 * @param {string} url
 * @returns {Object}
 */
export function getQueryObject (url) {
  url = url == null ? window.location.href : url;
  const search = url.substring(url.lastIndexOf('?') + 1);
  const obj = {};
  const reg = /([^?&=]+)=([^?&=]*)/g;
  search.replace(reg, (rs, $1, $2) => {
    const name = decodeURIComponent($1);
    let val = decodeURIComponent($2);
    val = String(val);
    obj[name] = val;
    return rs;
  });
  return obj;
}

/**
 * @param {string} input value
 * @returns {number} output value
 */
export function byteLength (str) {
  // returns the byte length of an utf8 string
  let s = str.length;
  for (let i = str.length - 1; i >= 0; i--) {
    const code = str.charCodeAt(i);
    if (code > 0x7f && code <= 0x7ff) s++;
    else if (code > 0x7ff && code <= 0xffff) s += 2;
    if (code >= 0xDC00 && code <= 0xDFFF) i--;
  }
  return s;
}

/**
 * @param {Array} actual
 * @returns {Array}
 */
export function cleanArray (actual) {
  const newArray = [];
  for (let i = 0; i < actual.length; i++) {
    if (actual[i]) {
      newArray.push(actual[i]);
    }
  }
  return newArray;
}

/**
 * @param {Object} json
 * @returns {Array}
 */
export function param (json) {
  if (!json) return '';
  return cleanArray(
    Object.keys(json).map(key => {
      if (json[key] === undefined) return '';
      return encodeURIComponent(key) + '=' + encodeURIComponent(json[key]);
    })
  ).join('&');
}

/**
 * @param {string} url
 * @returns {Object}
 */
export function param2Obj (url) {
  const search = decodeURIComponent(url.split('?')[1]).replace(/\+/g, ' ');
  if (!search) {
    return {};
  }
  const obj = {};
  const searchArr = search.split('&');
  searchArr.forEach(v => {
    const index = v.indexOf('=');
    if (index !== -1) {
      const name = v.substring(0, index);
      const val = v.substring(index + 1, v.length);
      obj[name] = val;
    }
  });
  return obj;
}

/**
 * @param {string} val
 * @returns {string}
 */
export function html2Text (val) {
  const div = document.createElement('div');
  div.innerHTML = val;
  return div.textContent || div.innerText;
}

/**
 * Merges two objects, giving the last one precedence
 * @param {Object} target
 * @param {(Object|Array)} source
 * @returns {Object}
 */
export function objectMerge (target, source) {
  if (typeof target !== 'object') {
    target = {};
  }
  if (Array.isArray(source)) {
    return source.slice();
  }
  Object.keys(source).forEach(property => {
    const sourceProperty = source[property];
    if (typeof sourceProperty === 'object') {
      target[property] = objectMerge(target[property], sourceProperty);
    } else {
      target[property] = sourceProperty;
    }
  });
  return target;
}

/**
 * @param {HTMLElement} element
 * @param {string} className
 */
export function toggleClass (element, className) {
  if (!element || !className) {
    return;
  }
  let classString = element.className;
  const nameIndex = classString.indexOf(className);
  if (nameIndex === -1) {
    classString += '' + className;
  } else {
    classString =
      classString.substr(0, nameIndex) +
      classString.substr(nameIndex + className.length);
  }
  element.className = classString;
}

/**
 * @param {string} type
 * @returns {Date}
 */
export function getTime (type) {
  if (type === 'start') {
    return new Date().getTime() - 3600 * 1000 * 24 * 90;
  } else if (type === 'timestamp') {
    return (new Date().getTime() / 1000).toString();
  } else {
    return new Date(new Date().toDateString());
  }
}

/**
 * @param {Function} func
 * @param {number} wait
 * @param {boolean} immediate
 * @return {*}
 */
export function debounce (func, wait, immediate) {
  let timeout, args, context, timestamp, result;

  const later = function () {
    // 据上一次触发时间间隔
    const last = +new Date() - timestamp;

    // 上次被包装函数被调用时间间隔 last 小于设定时间间隔 wait
    if (last < wait && last > 0) {
      timeout = setTimeout(later, wait - last);
    } else {
      timeout = null;
      // 如果设定为immediate===true，因为开始边界已经调用过了此处无需调用
      if (!immediate) {
        result = func.apply(context, args);
        if (!timeout) context = args = null;
      }
    }
  };

  return function (...args) {
    context = this;
    timestamp = +new Date();
    const callNow = immediate && !timeout;
    // 如果延时不存在，重新设定延时
    if (!timeout) timeout = setTimeout(later, wait);
    if (callNow) {
      result = func.apply(context, args);
      context = args = null;
    }

    return result;
  };
}

/**
 * This is just a simple version of deep copy
 * Has a lot of edge cases bug
 * If you want to use a perfect deep copy, use lodash's _.cloneDeep
 * @param {Object} source
 * @returns {Object}
 */
export function deepClone (source) {
  if (!source && typeof source !== 'object') {
    throw new Error('error arguments', 'deepClone');
  }
  const targetObj = source.constructor === Array ? [] : {};
  Object.keys(source).forEach(keys => {
    if (source[keys] && typeof source[keys] === 'object') {
      targetObj[keys] = deepClone(source[keys]);
    } else {
      targetObj[keys] = source[keys];
    }
  });
  return targetObj;
}

/**
 * @param {Array} arr
 * @returns {Array}
 */
export function uniqueArr (arr) {
  return Array.from(new Set(arr));
}

/**
 * @returns {string}
 */
export function createUniqueString () {
  const timestamp = +new Date() + '';
  const randomNum = parseInt((1 + Math.random()) * 65536) + '';
  return (+(randomNum + timestamp)).toString(32);
}

/**
 * Check if an element has a class
 * @param {HTMLElement} elm
 * @param {string} cls
 * @returns {boolean}
 */
export function hasClass (ele, cls) {
  return !!ele.className.match(new RegExp('(\\s|^)' + cls + '(\\s|$)'));
}

/**
 * Add class to element
 * @param {HTMLElement} elm
 * @param {string} cls
 */
export function addClass (ele, cls) {
  if (!hasClass(ele, cls)) ele.className += ' ' + cls;
}

/**
 * Remove class from element
 * @param {HTMLElement} elm
 * @param {string} cls
 */
export function removeClass (ele, cls) {
  if (hasClass(ele, cls)) {
    const reg = new RegExp('(\\s|^)' + cls + '(\\s|$)');
    ele.className = ele.className.replace(reg, ' ');
  }
}

/**
 * loading类型的toast
 * @param obj
 * @returns {ElMessageComponent}
 */
export function loadingToast(obj) {
  if (obj === undefined) {
    obj = {message: '正在请求', type: 'info', iconClass: 'el-icon-loading', duration: 10000 };
  }
  return toast({
    message: obj.message,
    type: obj.type,
    iconClass: obj.iconClass,
    duration: obj.duration
  });
}

export function notification (options) {
  if (options.showClose === undefined) {
    options.showClose = true;
  }
  if (options.duration === undefined) {
    options.duration = 3000;
  }
  return Notification(options);
}
export function info (options) {
  if (options.showClose === undefined) {
    options.showClose = true;
  }
  Message.info(options);
}
export function success (options) {
  if (options.showClose === undefined) {
    options.showClose = true;
  }
  Message.success(options);
}
export function error (options) {
  if (options.showClose === undefined) {
    options.showClose = true;
  }
  Message.error(options);
}
export function warning (options) {
  if (options.showClose === undefined) {
    options.showClose = true;
  }
  Message.warning(options);
}

export function getStorage (key) {
  let data = null;
  if (window.localStorage.getItem(key)) {
    data = window.localStorage.getItem(key);
  }
  return data;
}
export function setStorage (key, data) {
  window.localStorage.setItem(key, data);
}
export function removeStorage (key) {
  window.localStorage.removeItem(key);
}
export function clearStorage () {
  window.localStorage.clear();
}

export function greetings () {
  let now = new Date();
  let hour = now.getHours();
  let greetings = '您好';
  if (hour < 6) { greetings = '凌晨好！'; } else if (hour < 9) { greetings = '早上好！'; } else if (hour < 12) { greetings = '上午好！'; } else if (hour < 14) { greetings = '中午好！'; } else if (hour < 17) { greetings = '下午好！'; } else if (hour < 19) { greetings = '傍晚好！'; } else if (hour < 22) { greetings = '晚上好！'; } else { greetings = '夜里好！'; }
  return greetings;
}

export function useElementThemeCss (url) {
  let head = document.getElementsByTagName('HEAD').item(0);
  // head.getElementsByClassName('element-theme-css-file').remove()
  let style = document.createElement('link');
  style.href = url;
  style.rel = 'stylesheet';
  style.type = 'text/css';
  style.class = 'element-theme-css-file';
  style.setAttribute('class', 'element-theme-css-file');
  head.appendChild(style);
}

/**
 * isInteger(3) // true
 * isInteger(3.3) // false
 * isInteger('') // false
 * isInteger('3') // false
 * isInteger(true) // false
 * isInteger([]) // false
 * @param obj
 * @description 判断是否为整型
 * @returns {boolean}
 */
export function isInteger (obj) {
  return (obj | 0) === obj;
}

export function base64ToBlob (urlData, type) {
  let arr = urlData.split(',');
  let mime = arr[0].match(/:(.*?);/)[1] || type;
  // 去掉url的头，并转化为byte
  let bytes = window.atob(arr[1]);
  // 处理异常,将ascii码小于0的转换为大于0
  let ab = new ArrayBuffer(bytes.length);
  // 生成视图（直接针对内存）：8位无符号整数，长度1个字节
  let ia = new Uint8Array(ab);
  for (let i = 0; i < bytes.length; i++) {
    ia[i] = bytes.charCodeAt(i);
  }
  return new Blob([ab], {
    type: mime
  });
}

export function goBack (obj) {
  let view = obj.$route;
  obj.$store.dispatch('tagsView/delView', view).then(({ visitedViews }) => {
    toLastView(visitedViews, view, obj);
  });
}

function toLastView (visitedViews, view, obj) {
  const latestView = visitedViews.slice(-1)[0];
  if (latestView) {
    obj.$router.push(latestView.fullPath);
  } else {
    if (view.meta && view.meta.closeable === false) {
      obj.$router.replace({ path: '/redirect' + view.fullPath });
    } else {
      obj.$router.push('/');
    }
  }
}


export function cloneJson (json) {
  return JSON.parse(JSON.stringify(json));
}

export function uniqueArray (arr) {
  let res={};
  arr.forEach(item=>{
    res[item]=item;
  });
  return Object.values(res);
}
export function trimString(str) {
  if (typeof str === 'string') {
    return str.replace(/^\s+|\s+$/gm,'');
  }
  return str;
}

export function inArray (search, array) {
  for(let i in array){
    if(array[i] === search){
      return true;
    }
  }
  return false;
}

/**
 * 过滤表单字段和详情字段
 * @param item 表单项的配置
 * @param query 当前页面的传递的参数对象
 * @param form 表单键值对对象
 * @returns {boolean} true 不过滤｜false 过滤
 */
function filterFieldByMode (item, query, form) {
  return visibleFunc(item, form, query);
}

/**
 * 执行字符串作为js函数体，用于过滤表单项或详情项，如：
 * if(form.sex == 1 && form[field] != "") { return true;} else {return false}
 * @param item 表单项的配置
 * @param form 表单键值对对象
 * @param query 页面传递参数对象
 * @returns {boolean|*}  true：需要渲染｜false：不渲染的
 */
function visibleFunc (item, form, query) {
  if (item.visibleFunction) {
    try{
      return new Function('form','field', 'query', item.visibleFunction )(form, item.field, query);
    }catch(e) {
      console.log('visibleFunction error');
      console.log(e);
    }
  }
  return true;
}
function sortClass(sortData, prop) {
  const groupBy = (array, f) => {
    let groups = {};
    array.forEach((o) => {
      let group = JSON.stringify(f(o));
      groups[group] = groups[group] || [];
      groups[group].push(o);
    });
    return Object.keys(groups).map((group) => {
      return groups[group];
    });
  };
  return groupBy(sortData, (item) => {
    return item[prop];
  });
}
export function valueFilter (formArr, filterArr, formKey, filterKey, boolean = "after") {
  let tempArr = []
  for(let i of filterArr) {
    for(let j of formArr) {
      
      if(i[formKey] === j[filterKey]) {
        if(boolean == "front") {
          tempArr.push(i)
          break;
        } else {
          tempArr.push(j)
          break;
        }
      }
    }
  }
  console.log(tempArr)
  return tempArr
}

// 将表单分组分盒
export function generateGroupForm(formList) {
  // TODO 待优化
  let groupForm = [];
  const groupProp = 'group';
  const boxProp = 'box';

  if (formList && formList.length > 0) {
    let sortGroupData = sortClass(formList, groupProp);
    for (let i in sortGroupData) {
      let groupItems = [];
      let sortBoxData = sortClass(sortGroupData[i], boxProp);
      for (let j in sortBoxData) {
        let formData = [];
        for (let k in sortBoxData[j]){
          // if (!filterFieldByMode(sortBoxData[j][k], query, form)){
          //   continue
          // }
          // if (form[sortBoxData[j][k].field] !== undefined) {
          //   sortBoxData[j][k].value = form[sortBoxData[j][k].field]
          // }
          formData.push(sortBoxData[j][k]);
        }
        if (formData && formData.length > 0) {
          groupItems.push({
            title: sortBoxData[j][0][boxProp] || '',
            items: formData
          });
        }
      }
      groupForm.push({
        title: sortGroupData[i][0][groupProp] || '',
        validateFail:false,
        items: groupItems
      });
    }
  }

  return groupForm;
}

// 比特转字符串
export function converBitSize(limit){
  let size = "";
  if( limit < 0.1 * 1024 ){ //如果小于0.1KB转化成B
    size = limit.toFixed(2) + "B";
  }else if(limit < 0.1 * 1024 * 1024 ){//如果小于0.1MB转化成KB
    size = (limit / 1024).toFixed(2) + "KB";
  }else if(limit < 0.1 * 1024 * 1024 * 1024){ //如果小于0.1GB转化成MB
    size = (limit / (1024 * 1024)).toFixed(2) + "MB";
  }else{ //其他转化成GB
    size = (limit / (1024 * 1024 * 1024)).toFixed(2) + "GB";
  }

  let sizestr = size + "";
  let len = sizestr.indexOf(".");
  let dec = sizestr.substr(len + 1, 2);
  if(dec == "00"){//当小数点后为00时 去掉小数部分
    return sizestr.substring(0,len) + sizestr.substr(len + 3,2);
  }
  return sizestr;
}

export function toString(num) {
  if (num !== null && !isNaN(num)) {
    return num.toString();
  }
  return num;
}

export function getComponentByPath(path) {
  return resolve => {
    require.ensure([], (require) => {
      resolve(require(`@/views${path}.vue`));
    });
  };
}

/**
 * 税率验证正则，大于0 小于100的整数或小数，保留两位小数
 */
export const taxRateReg = {
  reg: /^\d\.([1-9]{1,2}|[0-9][1-9])$|^[1-9]\d{0,1}(\.\d{1,2}){0,1}$|^100(\.0{1,2}){0,1}$|^0\.0$|^0\.00$|^0$/,
  msg: '税率不能大于100的正数，且保留两位小数'
};

/**
 * 正数正则，大于0的数字，且最多保留三位小数
 * @type {{msg: string, reg: RegExp}}
 */
export const positiveNumReg = {
  reg: /^(([0-9]+)|([0-9]+\.[0-9]{0,3}))$/,
  msg: '只能输入最多保留三位小数的正数'
};

/**
 * 计算表格数据的总计
 * @param tableData
 * @param callback
 */
export function getTableSum(tableData, callback) {
  let sum = 0;
  if (tableData  && tableData.length > 0) {
    for (let i in tableData) {
      let row = tableData[i];
      let d = callback(row);
      d = d === undefined || isNaN(d) ? 0 : d;
      sum += d;
    }
  }
  return sum;
}

/**
 * 判断数组中对象的某个属性是否唯一
 * @param array     数组
 * @param attr      属性名称
 * @returns {boolean|*}  true: 有重复项  false：无重复
 */
export function arrayAttrUnique(array, attr) {
  if (!array || array.length < 1) {
    return false;
  }
  let arr = [];
  for (let i in array) {
    if(array[i][attr] === null || array[i][attr] === undefined) {
      continue;
    }
    arr.push(array[i][attr]);
  }
  let newArr = [...new Set(arr)];//利用SET去重
  return arr.length !== newArr.length;
}


/**
 * 构造树型结构数据
 * @param {*} data 数据源
 * @param {*} id id字段 默认 'id'
 * @param {*} parentId 父节点字段 默认 'parentId'
 * @param {*} children 孩子节点字段 默认 'children'
 * @param {*} rootId 根Id 默认 0
 */
 export function handleTree(data, id, parentId, children, rootId) {
	id = id || 'id'
	parentId = parentId || 'parentId'
	children = children || 'children'
	rootId = rootId || 0
	//对源数据深度克隆
	const cloneData = JSON.parse(JSON.stringify(data))
	//循环所有项
	const treeData =  cloneData.filter(father => {
	  let branchArr = cloneData.filter(child => {
		//返回每一项的子级数组
		return father[id] === child[parentId]
	  });
	  branchArr.length > 0 ? father.children = branchArr : '';
	  //返回第一层
	  return father[parentId] === rootId;
	});
	return treeData != '' ? treeData : data;
  }


  // 数组转树形
export function arrayToTree(arr, childName = "children", idKey = "id", pidKey = "pid") {
  arr.filter(item => {
    item[childName] = arr.filter(item2 => item2[pidKey] == item[idKey])
    return item.pid == 0;
  });
}

// 树形转数组
export function treeToArr(tree) {
  let arrs = [];
  let result = [];
  arrs = arrs.concat(tree);
  while (arrs.length) {
    let first = arrs.shift(); // 弹出第一个元素
    if (first.children) {
      //如果有children
      arrs = arrs.concat(first.children);
      delete first["children"];
    }
    result.push(first);
  }
  return result;
}

// 处理表头方法
export function processeField(data, k, fieldBefore, fieldAfter) {
  if(data[k].aliasName == fieldBefore) {
    let arr = data.filter(item => item.aliasName === fieldBefore)
    Vue.set(arr[0], "aliasName", fieldAfter)
  }
}

